package reliability.ui;

import reliability.MinimalPathsAndSectionsMethod;
import reliability.StatisticalModelingMethod;
import reliability.model.GraphModel;
import reliability.model.MinimalPathsAndSectionsMethodResults;
import reliability.model.StatisticalModelingMethodResults;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

public class ProgressDialog
    extends JDialog
    implements PropertyChangeListener
{
    private JProgressBar progressBar;
    private GraphModel graphModel;

    private StatisticalModelingMethod statisticalModelingMethod;
    private MinimalPathsAndSectionsMethod minimalPathsAndSectionsMethod;

    private StatisticalModelingMethodResults statisticalModelingMethodResults;
    private MinimalPathsAndSectionsMethodResults minimalPathsAndSectionsMethodResults;

    private boolean isCancelled = false;

    public ProgressDialog(JFrame frame, String title, GraphModel model)
    {
        super(frame, title, true);
        graphModel = model;
        setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent windowEvent)
            {
                isCancelled = true;
                handleWindowClose();
            }
        });

        JPanel dialogContentPane = new JPanel();
        dialogContentPane.setLayout(new FlowLayout());
        dialogContentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        dialogContentPane.add(new JLabel("Прогресс: "));

        progressBar = new JProgressBar(0, 100);
        progressBar.setStringPainted(true);
        progressBar.setValue(0);
        dialogContentPane.add(progressBar);

        setContentPane(dialogContentPane);
        setLocationRelativeTo(frame);
        setResizable(false);
        pack();
        performTask();
    }

    public void propertyChange(PropertyChangeEvent evt)
    {
        Object evtSource = evt.getSource();
        if (evtSource.equals(statisticalModelingMethod))
        {
            handleStatisticalMethodPropertyChange(evt);
        }
        else if (evtSource.equals(minimalPathsAndSectionsMethod))
        {
            handleMinimalPathsAndSectionsMethodPropertyChange(evt);
        }
    }

    public boolean isCancelled()
    {
        return isCancelled;
    }

    private void handleStatisticalMethodPropertyChange(PropertyChangeEvent evt)
    {
        String propertyName = evt.getPropertyName();
        if (propertyName.equals("progress"))
        {
            int progress = (Integer) evt.getNewValue();
            progressBar.setValue(progress / 2);
        }
        else if (propertyName.equals("state"))
        {
            if ((statisticalModelingMethod.getState() == SwingWorker.StateValue.DONE) &&
                    !statisticalModelingMethod.isCancelled())
            {
                try
                {
                    statisticalModelingMethodResults = statisticalModelingMethod.get();
                    if (statisticalModelingMethodResults == null && !isCancelled)
                    {
                        JOptionPane.showMessageDialog(this,
                                "Граф сети должен быть связным!",
                                "Ошибка в графе",
                                JOptionPane.ERROR_MESSAGE
                        );
                        isCancelled = true;
                        handleWindowClose();
                    }
                    minimalPathsAndSectionsMethod = new MinimalPathsAndSectionsMethod(graphModel);
                    minimalPathsAndSectionsMethod.addPropertyChangeListener(this);
                    minimalPathsAndSectionsMethod.execute();
                }
                catch (Exception ignored){ }
            }
        }
    }

    private void handleMinimalPathsAndSectionsMethodPropertyChange(PropertyChangeEvent evt)
    {
        String propertyName = evt.getPropertyName();
        if (propertyName.equals("progress"))
        {
            int progress = (Integer) evt.getNewValue();
            progressBar.setValue(50 + progress / 2);
        }
        else if (propertyName.equals("state"))
        {
            if ((minimalPathsAndSectionsMethod.getState() == SwingWorker.StateValue.DONE) &&
                    !minimalPathsAndSectionsMethod.isCancelled())
            {
                try
                {
                    minimalPathsAndSectionsMethodResults = minimalPathsAndSectionsMethod.get();
                    handleWindowClose();
                }
                catch (Exception ignored){ }
            }
        }
    }

    public void handleWindowClose()
    {
        if (statisticalModelingMethod != null && !statisticalModelingMethod.isCancelled())
        {
            statisticalModelingMethod.cancel(true);
        }
        if (minimalPathsAndSectionsMethod != null && !minimalPathsAndSectionsMethod.isCancelled())
        {
            minimalPathsAndSectionsMethod.cancel(true);
        }
        progressBar.setValue(0);
        dispose();
    }

    public StatisticalModelingMethodResults getStatisticalModelingMethodResults()
    {
        return statisticalModelingMethodResults;
    }

    public MinimalPathsAndSectionsMethodResults getMinimalPathsAndSectionsMethodResults()
    {
        return minimalPathsAndSectionsMethodResults;
    }

    public void setVisible(boolean isVisible)
    {
        super.setVisible(isVisible);
    }

    private void performTask()
    {
        statisticalModelingMethod = new StatisticalModelingMethod(graphModel);
        statisticalModelingMethod.addPropertyChangeListener(this);
        statisticalModelingMethod.execute();
    }
}
